package com.mezz.bones.im.gateway.action.impl;
import cn.hutool.core.util.StrUtil;
import com.mezz.bones.im.common.domain.user.ImUserConnectInfo;
import com.mezz.bones.im.common.enums.ActionCodeEnum;
import com.mezz.bones.im.common.exception.ImBaseException;
import com.mezz.bones.im.common.message.base.MessageHeader;
import com.mezz.bones.im.common.message.body.in.UserLoginReq;
import com.mezz.bones.im.common.result.ImResult;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.gateway.action.interfaces.AbstractSysMessageAction;
import com.mezz.bones.im.gateway.manager.UserConnectInfoManager;
import com.mezz.bones.im.gateway.manager.UserIpManager;
import com.mezz.bones.im.gateway.service.IUserChannelService;
import com.mezz.bones.im.gateway.util.ChannelUtil;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.InetSocketAddress;

/**
 * @Author: zhuang
 * @Date: 2024/11/29 18:39
 * @Description: TODO
 * @Version: 1.0
 **/

@Service
public class LoginSysAction extends AbstractSysMessageAction<UserLoginReq> {

    @Resource
    private UserIpManager userIpManager;


    @Resource
    private IUserChannelService userChannelService;

    @Resource
    private UserConnectInfoManager userConnectInfoManager;

    @Override
    public String tag() {
        return ActionCodeEnum.CLIENT_USER_LOGIN.getCode();
    }

    @Override
    public void checkParam(UserLoginReq req){
        if(req == null || StrUtil.isBlank(req.getToken())){
            throw new ImBaseException(ImResultCode.PARAM_ERROR,"缺少token参数");
        }
    }

    @Override
    public void process(MessageHeader header, UserLoginReq req, ChannelHandlerContext ctx) {


            ImUserConnectInfo userConnectInfo = userConnectInfoManager.getUserConnectInfo(ctx);
            if(userConnectInfo != null){
                //已验证成功
                ctx.channel().writeAndFlush(ImResult.data(ImResultCode.SUCCESS,header.getTraceId(), ActionCodeEnum.CLIENT_USER_LOGIN.getCode(), null));
                return;
            }

            //X-Forwarded-For nginx http 代理通过这个参数传递 如果是TCP连接则没有问题
            String clientIp = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
            log.info("Client IP: {}", clientIp);
            //设置channel上下文IP信息
            userIpManager.setIp(ctx,clientIp);

            userChannelService.validMsgHeader(header);
            header.setToken(req.getToken());

            //初始化用户信息 绑定channel 连接设备状态信息等
            ImUserConnectInfo imUserConnectInfo = userChannelService.authUserInfo(ctx, header);
            imUserConnectInfo.setIp(clientIp);
            userChannelService.initOnLine(imUserConnectInfo,ctx);

            log.info("用户登录成功: userId = {}, deviceType = {}, clientIp = {}, imei = {}",
                    imUserConnectInfo.getUserId(),
                    imUserConnectInfo.getDeviceType(),
                    clientIp,
                    imUserConnectInfo.getImei());

            //登录成功后 把对应的未认证的map映射移除掉
            userChannelService.removeUnAuthChannel(ctx);

            ctx.channel().writeAndFlush(ImResult.data(ImResultCode.SUCCESS,header.getTraceId(), ActionCodeEnum.CLIENT_USER_LOGIN.getCode(), null));


    }

}
